import org.testng.Assert;
import org.testng.annotations.Test;
import java.awt.*;
import java.awt.event.ActionEvent;

public class SnakeGameIntegrationTests {

    // 测试蛇撞墙行为
    @Test
    public void testSnakeHitsWall() {
        Board board = new Board();
        Snake snake = board.getSnake();

        // 计算移动到右边界前的步数（留2个单位的缓冲）
        int steps = board.getB_WIDTH() / board.getDOT_SIZE() - 2;
        for (int i = 0; i < steps; i++) {
            board.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null));
        }

        // 最后一次移动触发撞墙
        board.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null));
        Assert.assertFalse(snake.isAlive(), "蛇撞墙后应死亡");
    }

    // 测试蛇自撞行为
    @Test
    public void testSnakeHitsItself() {
        Board board = new Board(10); // 假设构造参数为面板大小
        Snake snake = board.getSnake();

        // 模拟蛇形成环形路径：右 → 下 → 左 → 上（触发自撞）
        changeDirectionAndMove(board, Snake.Direction.DOWN);
        changeDirectionAndMove(board, Snake.Direction.LEFT);
        changeDirectionAndMove(board, Snake.Direction.UP);

        Assert.assertFalse(snake.isAlive(), "蛇撞到自身应死亡");
    }

    // 测试苹果再生行为
    @Test
    public void testAppleRegeneratesAfterBeingEaten() {
        Board board = new Board();
        Apple apple = board.getApple();
        Snake snake = board.getSnake();

        // 将苹果放置在蛇的下一步位置
        Point nextPos = (Point) snake.getHeadPosition().clone();
        nextPos.translate(1, 0); // 假设蛇向右移动
        apple.setPosition(nextPos.x, nextPos.y);

        Point oldApplePos = new Point(apple.getPosition());

        // 触发吃苹果事件
        board.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null));

        // 验证苹果位置已更新
        Assert.assertNotEquals(
                apple.getPosition(),
                oldApplePos,
                "苹果应在被吃掉后重新生成到新位置"
        );
    }

    // 辅助方法：改变方向并移动一步
    private void changeDirectionAndMove(Board board, Snake.Direction direction) {
        board.getSnake().setCurrentDirection(direction);
        board.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null));
    }
}